<template>
  <div class="military-gantt-container">
    <!-- 加载遮罩层 -->
    <div v-if="isLoading" class="gantt-loading-overlay">
      <img :src="loadingGif" alt="加载中" class="loading-gif" />
      <p class="loading-text">智能体数据生成中...</p>
    </div>

    <!-- A. 顶部控制栏 -->
    <div class="gantt-header-bar">
      <div class="header-left">
        <div class="time-info">
          <span class="label">D日:</span> <span class="value">{{ ganttData.simulation.currentDate }}</span>
        </div>
        <div class="time-info">
          <span class="label">K时刻:</span> <span class="value">{{ ganttData.simulation.currentTime }}</span>
        </div>
      </div>

      <div class="header-right">
        <div class="control-group">
          <!-- 刷新按钮 -->
          <div class="refresh-btn" @click="handleRefresh" title="刷新数据">
            <el-icon>
              <RefreshRight />
            </el-icon>
          </div>
          <!-- 顶层刻度 -->
          <div class="select-box">
            <span>顶层刻度</span>
            <div class="select-wrapper" ref="topScaleRef">
              <div class="select-trigger" @click="showTopScaleDropdown = !showTopScaleDropdown">
                <span>{{ selectedTopScale }}</span>
                <el-icon class="arrow-icon" :class="{ 'is-open': showTopScaleDropdown }">
                  <CaretBottom />
                </el-icon>
              </div>
              <!-- 下拉菜单 -->
              <div v-if="showTopScaleDropdown" class="dropdown-menu">
                <div v-for="opt in topScaleOptions" :key="opt.value" class="dropdown-item"
                  :class="{ active: selectedTopScale === opt.label }" @click="handleScaleSelect('top', opt)">
                  {{ opt.label }}
                </div>
              </div>
            </div>
          </div>

          <!-- 底层刻度 -->
          <div class="select-box">
            <span>底层刻度</span>
            <div class="select-wrapper" ref="bottomScaleRef">
              <div class="select-trigger" @click="showBottomScaleDropdown = !showBottomScaleDropdown">
                <span>{{ selectedBottomScale }}</span>
                <el-icon class="arrow-icon" :class="{ 'is-open': showBottomScaleDropdown }">
                  <CaretBottom />
                </el-icon>
              </div>
              <!-- 下拉菜单 -->
              <div v-if="showBottomScaleDropdown" class="dropdown-menu">
                <div v-for="opt in bottomScaleOptions" :key="opt.value" class="dropdown-item"
                  :class="{ active: selectedBottomScale === opt.label }" @click="handleScaleSelect('bottom', opt)">
                  {{ opt.label }}
                </div>
              </div>
            </div>
          </div>

          <!-- 演示按钮 -->
          <button class="play-btn" @click="handlePlay">
            开始演练
            <el-icon class="btn-icon" style="vertical-align: middle; margin-left: 4px;">
              <CaretRight />
            </el-icon>
          </button>
        </div>
      </div>
    </div>

    <!-- B. 主体内容区 -->
    <div class="gantt-body">
      <!-- B1. 左侧树形列表 -->
      <div class="left-tree-panel">
        <div class="panel-header">作战计划</div>
        <div class="tree-content" ref="leftScrollRef" @scroll="syncScroll('left')">
          <div v-for="row in flattenedRows" :key="row.id" class="tree-row"
            :class="{ 'is-group': row.isGroup, 'is-active': hoverRowId === row.id }"
            :style="{ paddingLeft: (row.level * 20 + 10) + 'px' }" @mouseenter="handleMouseEnter($event, row)"
            @mousemove="handleMouseMove" @mouseleave="handleMouseLeave">
            <!-- 展开/折叠图标 -->
            <span class="expand-icon" @click.stop="toggleExpand(row)"
              :style="{ visibility: row.isGroup ? 'visible' : 'hidden' }">
              <el-icon v-if="row.expanded">
                <CaretBottom />
              </el-icon>
              <el-icon v-else>
                <CaretRight />
              </el-icon>
            </span>

            <!-- 复选框 (点击仅切换视觉状态) -->
            <div class="checkbox" :class="{ checked: row.checked }" @click.stop="toggleCheck(row)">
              <el-icon v-if="row.checked" class="check-icon"><Select /></el-icon>
            </div>

            <!-- 名称 -->
            <span class="row-name">{{ row.name }}</span>
          </div>
        </div>
      </div>

      <!-- B2. 右侧图表区域 -->
      <div class="right-chart-panel">
        <!-- 新增：头部滚动容器 (用于同步横向滚动) -->
        <div class="header-scroll-container" ref="headerScrollRef">
          <!-- 1. 时间轴头 (Ruler Style) -->
          <div class="timeline-header" :style="{ width: totalWidth + 'px' }">
            <div class="ruler-container">
              <div v-for="(tick, idx) in timeScaleTicks" :key="idx" class="ruler-tick"
                :class="{ 'major-tick': tick.isMajor, 'minor-tick': !tick.isMajor }"
                :style="{ left: tick.left + 'px' }">
                
                <!-- D日 Badge (替代 00) -->
                <div v-if="tick.label === '00'" class="k-header-badge" 
                     :style="{ 
                       left: '0', 
                       opacity: Math.abs(tick.left - kTimePosition) < 35 ? 0 : 1 
                     }">
                  <div class="kh-title" style="color: #D4FFEF;">{{ tick.dayLabel }}</div>
                  <div class="kh-value">00</div>
                </div>

                <span v-else-if="tick.isMajor" class="tick-label" :style="{
                  opacity: Math.abs(tick.left - kTimePosition) < 35 ? 0 : 1,
                  transform: tick.left === 0 ? 'translateX(0)' : (tick.left === totalWidth ? 'translateX(-100%)' : 'translateX(-50%)')
                }">
                  {{ tick.label }}
                </span>
              </div>

              <!-- K时刻 Badge (In Header) -->
              <div class="k-header-badge" :style="{ left: kTimePosition + 'px' }">
                <div class="kh-title">K时刻</div>
                <div class="kh-value">{{ kTimeHour }}</div>
                <!-- <div class="kh-arrow"></div> -->
              </div>
            </div>
          </div>
        </div>

        <div class="chart-scroll-container" ref="rightScrollRef" @scroll="syncScroll('right')">

          <!-- 2. 绘图内容区 -->
          <div class="chart-content"
            :style="{ width: totalWidth + 'px', height: flattenedRows.length * rowHeight + 'px' }">

            <!-- 背景网格 -->
            <div class="grid-background">
              <div v-for="(tick, idx) in timeScaleTicks" :key="idx" class="grid-col-line"
                :style="{ left: tick.left + 'px' }"></div>
              <div v-for="(row, idx) in flattenedRows" :key="row.id" class="grid-row-line"
                :style="{ top: (idx + 1) * rowHeight + 'px' }"></div>
            </div>

            <!-- K时刻线 (贯穿线) -->
            <div class="k-time-line" :style="{
              left: kTimePosition + 'px',
              height: (flattenedRows.length * rowHeight) + 'px'
            }">
            </div>

            <!-- 任务渲染层 -->
            <div class="task-layers">
              <div v-for="(row, rowIndex) in flattenedRows" :key="row.id" class="task-row-layer"
                :style="{ top: rowIndex * rowHeight + 'px', height: rowHeight + 'px' }">
                <template v-if="row.waypoints && row.waypoints.length">
                  <!-- 1. 连线段 (动态计算) -->
                  <div v-for="(seg, sIdx) in getSegments(row.waypoints)" :key="`seg-${sIdx}`" class="timeline-segment"
                    :class="seg.style" :style="getSegmentStyle(seg)">
                  </div>

                  <!-- 2. 统一航点图标 (包含关键点和中间悬浮点) -->
                  <div v-for="(wp, wIdx) in row.waypoints" :key="`wp-${wIdx}`" class="waypoint-node"
                    :class="getIconClass(wp.type)" :style="{ left: getPxByTime(wp.time) + 'px' }"
                    @mouseenter="handleChartPointEnter($event, wp)" @mouseleave="handleChartPointLeave">

                    <!-- 图标主体 -->
                    <div class="wp-icon">
                      <img v-if="wp.type === 'AIRPORT'" :src="iconAirportTakeoff" class="custom-icon" />
                      <img v-else-if="wp.type === 'ENTRY_POINT' || wp.type === 'EXIT_POINT'"
                        :src="iconAirportLanding" class="custom-icon" />
                      <img v-else-if="wp.type === 'HOVER_POINT'" :src="iconWaypoint" class="point-icon" />
                    </div>

                    <!-- 文字标签 (仅关键点显示，悬浮点不显示或者只在悬浮时显示) -->
                    <div class="wp-label" v-if="wp.type !== 'HOVER_POINT'">{{ wp.label }}</div>
                  </div>
                </template>
              </div>
            </div>

          </div>
        </div>
      </div>
    </div>
    <!-- 全局悬浮详情框 (Fixed定位 + Teleport脱离缩放容器) -->
    <Teleport to="body">
      <div v-if="tooltip.visible" class="row-detail-tooltip"
        :style="{ left: tooltip.left + 'px', top: tooltip.top + 'px' }">
        <div v-for="(val, key) in tooltip.content" :key="key" class="detail-item">
          <span class="d-label">{{ key }}:</span> {{ val }}
        </div>
      </div>
    </Teleport>

    <!-- 图表点悬浮详情框 (Fixed定位 + Teleport) -->
    <Teleport to="body">
      <div v-if="chartTooltip.visible" class="chart-point-tooltip"
        :style="{ left: chartTooltip.left + 'px', top: chartTooltip.top + 'px' }">
        <div class="hb-row">地点: {{ chartTooltip.location }}</div>
        <div class="hb-row">时间: {{ chartTooltip.time }}</div>
        <div class="hb-arrow"></div>
      </div>
    </Teleport>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, nextTick, watch } from 'vue'
import { CaretBottom, CaretRight, RefreshRight, Select } from '@element-plus/icons-vue'
import {
  useMinMaxTime,
  useStartDateTime,
  useTotalHours,
  useHourWidth,
  useTickIntervalMins,
  useTotalWidth,
  useFlattenedRows,
  useTimeScaleTicks,
  useKTimePosition,
  useKTimeHour
} from '../utils/GanttChart'
import '@/style/GanttChart.css'
const loadingGif = new URL('../../assets/Common/loading-spinner.gif', import.meta.url).href
const iconAirportTakeoff = new URL('../../assets/GanttChart/icon-airport-takeoff.png', import.meta.url).href
const iconAirportLanding = new URL('../../assets/GanttChart/icon-airport-landing.png', import.meta.url).href
const iconWaypoint = new URL('../../assets/GanttChart/icon-waypoint.png', import.meta.url).href

interface Props {
  receivedMessage?: string | any
  isLoading?: boolean
}
const props = defineProps<Props>()

// 下拉菜单状态
const showTopScaleDropdown = ref(false)
const showBottomScaleDropdown = ref(false)
const selectedTopScale = ref('1天')
const selectedBottomScale = ref('15分钟')
const topScaleRef = ref<HTMLElement | null>(null)
const bottomScaleRef = ref<HTMLElement | null>(null)

// 刻度选项
const topScaleOptions = [
  { label: '1天', value: '1d' },
  { label: '2天', value: '2d' },
  { label: '3天', value: '3d' },
  { label: '1周', value: '1w' }
]
const bottomScaleOptions = [
  { label: '15分钟', value: '15m' },
  { label: '30分钟', value: '30m' },
  { label: '1小时', value: '1h' },
  { label: '2小时', value: '2h' },
  { label: '4小时', value: '4h' },
  { label: '8小时', value: '8h' },
  { label: '12小时', value: '12h' }
]

// 点击外部关闭下拉菜单
const handleClickOutside = (event: MouseEvent) => {
  if (topScaleRef.value && !topScaleRef.value.contains(event.target as Node)) {
    showTopScaleDropdown.value = false
  }
  if (bottomScaleRef.value && !bottomScaleRef.value.contains(event.target as Node)) {
    showBottomScaleDropdown.value = false
  }
}

// 初始化任务状态：前端强制写死默认值
const initTasks = () => {
  if (!ganttData.rawTasks || ganttData.rawTasks.length === 0) return
  
  const traverseForInitTasks = (nodes: any[]) => {
    nodes.forEach(node => {
      const isGroup = !!(node.children && Array.isArray(node.children))
      // 强制设置默认状态
      if (isGroup) {
        node.expanded = true
      } else {
        node.checked = false
      }

      if (isGroup) {
        traverseForInitTasks(node.children)
      }
    })
  }
  traverseForInitTasks(ganttData.rawTasks)
  
  // 触发更新
  ganttData._updateTrigger++
}

let resizeObserver: ResizeObserver | null = null

onMounted(() => {
  document.addEventListener('click', handleClickOutside)
  initTasks() // 初始化任务状态

  // 初始化容器宽度
  if (rightScrollRef.value) {
    containerWidth.value = rightScrollRef.value.clientWidth

    // 监听容器大小变化
    resizeObserver = new ResizeObserver(entries => {
      for (const entry of entries) {
        containerWidth.value = entry.contentRect.width
      }
    })
    resizeObserver.observe(rightScrollRef.value)
  }

  // 延迟一点以确保布局完成
  setTimeout(() => {
    centerKTime()
  }, 100)
})

onUnmounted(() => {
  document.removeEventListener('click', handleClickOutside)
  if (resizeObserver) {
    resizeObserver.disconnect()
  }
})

// Mock 数据 (完全解耦样式)
const ganttData = reactive<{
  simulation: {
    currentDate: string
    currentTime: string
  }
  rawTasks: any[]
  _updateTrigger: number  // 用于强制触发更新
}>({
  simulation: {
    currentDate: "",
    currentTime: "",
  },
  rawTasks: [],
  _updateTrigger: 0
})

// 监听 receivedMessage 变化，更新 ganttData
watch(() => props.receivedMessage, (newValue, oldValue) => {
  // 避免重复触发：如果新旧值相同（引用相同），跳过
  if (newValue === oldValue) return
  
  if (newValue) {
    try {
      // 如果是字符串，尝试解析为 JSON
      const data = typeof newValue === 'string' ? JSON.parse(newValue) : newValue
      
      // 更新 ganttData
      if (data.simulation) {
        ganttData.simulation = { ...data.simulation }
      }
      if (data.rawTasks && Array.isArray(data.rawTasks)) {
        ganttData.rawTasks = [...data.rawTasks]
      }
      
      // 初始化任务状态
      nextTick(() => {
        initTasks()
        // 延迟居中 K时刻
        setTimeout(() => {
          centerKTime()
        }, 100)
      })
    } catch (error) {
      console.error('[GanttChart] 解析 receivedMessage 失败:', error)
    }
  }
}, { immediate: true })

// 视图配置
const rowHeight = 68// 行高

// 使用重构后的计算属性 hooks
const minMaxTime = useMinMaxTime(ganttData)

const startDateTime = useStartDateTime(ganttData, selectedTopScale, minMaxTime)

const totalHours = useTotalHours(ganttData, selectedTopScale, startDateTime, minMaxTime)

const containerWidth = ref(0) // 容器宽度监听
const hourWidth = useHourWidth(selectedBottomScale, containerWidth, totalHours)

const tickIntervalMins = useTickIntervalMins(selectedBottomScale)

const totalWidth = useTotalWidth(hourWidth, totalHours)
const leftScrollRef = ref<HTMLElement | null>(null)
const rightScrollRef = ref<HTMLElement | null>(null)
const headerScrollRef = ref<HTMLElement | null>(null)
const hoverRowId = ref<string | null>(null)


// 样式映射函数 (Mapper)

// 3. 动态计算每小时宽度 (Bottom Scale - Zoom Level)
// 根据起点和终点类型决定连线样式
const getSegmentClass = (startType: string, endType: string) => {
  if (startType === 'AIRPORT' && endType === 'ENTRY_POINT') return 'segment-gradient' // 巡航
  if (startType === 'ENTRY_POINT' && endType === 'EXIT_POINT') return 'segment-solid' // 攻击/作战
  if (startType === 'EXIT_POINT' && endType === 'AIRPORT') return 'segment-dashed'    // 返航
}

const getIconClass = (type: string) => {
  const map: Record<string, string> = {
    'AIRPORT': 'icon-plane',
    'ENTRY_POINT': 'icon-target', // 进入点用靶心/实心点
    'EXIT_POINT': 'icon-target',  // 退出点用靶心/实心点
    'HOVER_POINT': 'icon-heart'   // 中间悬浮点(爱心)
  }
  return map[type] || 'icon-dot'
}

// 辅助：从混合的 waypoints 中提取连线段
const getSegments = (waypoints: any[]) => {
  // 1. 过滤出关键节点 (非悬浮点)
  const keyPoints = waypoints.filter(wp => wp.type !== 'HOVER_POINT')
  const segments = []

  // 2. 两两连接生成线段
  for (let i = 0; i < keyPoints.length - 1; i++) {
    const start = keyPoints[i]
    const end = keyPoints[i + 1]
    segments.push({
      fromTime: start.time,
      toTime: end.time,
      style: getSegmentClass(start.type, end.type)
    })
  }
  return segments
}

const flattenedRows = useFlattenedRows(ganttData)

const timeScaleTicks = useTimeScaleTicks(ganttData, startDateTime, totalHours, hourWidth, tickIntervalMins)

// 辅助：根据时间字符串 HH:mm 获取像素偏移
const getPxByTime = (timeStr: string) => {
  if (!timeStr) return 0

  let targetTime: Date

  // 判断是否包含日期
  if (timeStr.includes(' ') || timeStr.includes('-')) {
    // 完整日期格式
    targetTime = new Date(timeStr.replace(/-/g, '/'))
  } else {
    // 只有时间，假设是当前推演日期
    // 注意：这里假设所有 HH:mm 都在 D日
    const datePart = ganttData.simulation.currentDate 
    targetTime = new Date(`${datePart.replace(/-/g, '/')} ${timeStr}`)
  }

  if (isNaN(targetTime.getTime())) return 0

  // 计算差值 (毫秒)
  const diffMs = targetTime.getTime() - startDateTime.value.getTime()
  const diffHours = diffMs / (1000 * 60 * 60)

  const px = diffHours * hourWidth.value
  return px
}

const kTimePosition = useKTimePosition(ganttData, getPxByTime)

const kTimeHour = useKTimeHour(ganttData)

// 自动居中 K时刻
const centerKTime = () => {
  if (!rightScrollRef.value || !headerScrollRef.value) return
  const containerWidth = rightScrollRef.value.clientWidth
  const kPos = kTimePosition.value

  // 目标 scrollLeft
  const targetScroll = kPos - (containerWidth / 2)

  rightScrollRef.value.scrollLeft = targetScroll
  // headerScrollRef 会通过 syncScroll 同步，或者手动同步
  headerScrollRef.value.scrollLeft = targetScroll
}

onMounted(() => {
  document.addEventListener('click', handleClickOutside)
  initTasks() // 初始化任务状态
  // 延迟一点以确保布局完成
  setTimeout(() => {
    centerKTime()
  }, 100)
})

// 辅助：获取连线样式
const getSegmentStyle = (seg: any) => {
  const left = getPxByTime(seg.fromTime)
  const right = getPxByTime(seg.toTime)
  return {
    left: left + 'px',
    width: (right - left) + 'px'
  }
}

// 交互：折叠/展开
const toggleExpand = (row: any) => {
  const findAndToggle = (nodes: any[]): boolean => {
    for (let i = 0; i < nodes.length; i++) {
      const node = nodes[i]
      if (node.id === row.id) {
        node.expanded = !node.expanded
        // 触发更新
        ganttData._updateTrigger++
        return true
      }
      if (node.children && Array.isArray(node.children)) {
        if (findAndToggle(node.children)) return true
      }
    }
    return false
  }
  
  if (ganttData.rawTasks && ganttData.rawTasks.length > 0) {
    findAndToggle(ganttData.rawTasks)
  }
}

// 交互：复选框
const toggleCheck = (row: any) => {
  const findAndToggle = (nodes: any[]): boolean => {
    for (let i = 0; i < nodes.length; i++) {
      const node = nodes[i]
      if (node.id === row.id) {
        node.checked = !node.checked
        // 触发更新
        ganttData._updateTrigger++
        return true
      }
      if (node.children && Array.isArray(node.children)) {
        if (findAndToggle(node.children)) return true
      }
    }
    return false
  }
  
  if (ganttData.rawTasks && ganttData.rawTasks.length > 0) {
    findAndToggle(ganttData.rawTasks)
  }
}

// 交互：滚动同步
const syncScroll = (source: 'left' | 'right') => {
  if (!leftScrollRef.value || !rightScrollRef.value) return

  if (source === 'left') {
    rightScrollRef.value.scrollTop = leftScrollRef.value.scrollTop
  } else {
    leftScrollRef.value.scrollTop = rightScrollRef.value.scrollTop
    // 同步头部横向滚动
    if (headerScrollRef.value) {
      headerScrollRef.value.scrollLeft = rightScrollRef.value.scrollLeft
    }
  }
}

// Tooltip 交互逻辑
const tooltip = reactive({
  visible: false,
  left: 0,
  top: 0,
  content: {} as any
})

// Chart Tooltip 交互逻辑
const chartTooltip = reactive({
  visible: false,
  left: 0,
  top: 0,
  location: '',
  time: ''
})

const handleChartPointEnter = (e: MouseEvent, wp: any) => {
  const target = e.currentTarget as HTMLElement
  const rect = target.getBoundingClientRect()
  chartTooltip.location = wp.label || wp.location
  chartTooltip.time = wp.time
  chartTooltip.visible = true
  // 计算位置: 元素中心上方
  chartTooltip.left = rect.left + rect.width / 2
  chartTooltip.top = rect.top - 8 // 稍微向上偏移
}

const handleChartPointLeave = () => {
  chartTooltip.visible = false
}

const handleMouseEnter = (e: MouseEvent, row: any) => {
  hoverRowId.value = row.id
  if (row.isGroup) {
    tooltip.visible = false
    return
  }
  tooltip.content = row.detail
  tooltip.visible = true
  updateTooltipPosition(e)
}

const handleMouseMove = (e: MouseEvent) => {
  if (tooltip.visible) {
    updateTooltipPosition(e)
  }
}

const handleMouseLeave = () => {
  hoverRowId.value = null
  tooltip.visible = false
}

const updateTooltipPosition = (e: MouseEvent) => {
  // 偏移一点，避免鼠标遮挡，显示在右下角
  tooltip.left = e.clientX + 15
  tooltip.top = e.clientY + 15
}

// 顶部按钮交互
const handleRefresh = () => {
  // 默认选中第一个
  selectedTopScale.value = topScaleOptions[0].label
  selectedBottomScale.value = bottomScaleOptions[0].label

  const query = {
    topScale: topScaleOptions[0].value,
    bottomScale: bottomScaleOptions[0].value
  }
  console.log("刷新数据", query)

  // 刷新后重新居中
  nextTick(() => {
    centerKTime()
  })
}

const handleScaleSelect = (type: 'top' | 'bottom', option: any) => {
  if (type === 'top') {
    selectedTopScale.value = option.label
    showTopScaleDropdown.value = false
  } else {
    selectedBottomScale.value = option.label
    showBottomScaleDropdown.value = false
  }

  // 获取当前选中的值
  const topVal = topScaleOptions.find(opt => opt.label === selectedTopScale.value)?.value
  const bottomVal = bottomScaleOptions.find(opt => opt.label === selectedBottomScale.value)?.value

  console.log("query", { topScale: topVal, bottomScale: bottomVal })

  // 切换选项后重新居中
  nextTick(() => {
    centerKTime()
  })
}

const handlePlay = () => console.log("点击演示 (Play clicked)")

</script>

<style scoped>
.military-gantt-container {
  position: relative; /* 确保遮罩层绝对定位相对于此容器 */
}

.gantt-loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
  z-index: 1000; /* 高于容器内其他元素 */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
}

.loading-gif {
  width: 80px;
  height: 80px;
  object-fit: contain;
}

.loading-text {
  font-family: 'Source Han Sans', sans-serif;
  font-size: 16px;
  font-weight: 400;
  color: #D4FFEF;
  opacity: 0.8;
  animation: pulse 1.5s ease-in-out infinite;
  margin: 0;
}

@keyframes pulse {
  0%, 100% { opacity: 0.5; }
  50% { opacity: 1; }
}

/* 样式已移至单独的CSS文件 */
</style>
